
#include <cstring>
#include <unistd.h>

#include "epoll_poller.h"
#include "logger.h"
#define MUDEBUG
/**
 * epoll_create
 * 
 * epoll_ctl  添加感兴趣的事件
 * epoll_wait 
 * 
 */

// 这里是Channel 的转态
const int kNew = -1;    // 
const int kAdded = 1;
const int kDeleted = 2;

EPollPoller::EPollPoller(EventLoop * eventloop)
    : Poller(eventloop)
    , epollfd_(epoll_create1(EPOLL_CLOEXEC))
    , events_(kInitEventListSize)
{
    if(epollfd_ < 0){
        LOG_FATAL("epoll_create error:%d \n", errno);
    }

}
EPollPoller::~EPollPoller () {
    close(epollfd_);
}


TimeStamp EPollPoller::poll(int timeout, ChannelList* activateChannels){
    LOG_INFO("func %s -> fd total count:%d \n", __FUNCTION__, channels_.size());
    // vector是连续存储的
    int numEvents = epoll_wait(epollfd_, &*events_.begin(), events_.size(), timeout);
    // 保存错误号 与返回时间
    int savedErrno = errno;
    TimeStamp now(TimeStamp::now());
    if(numEvents >0){
        LOG_INFO("EPollPoller::poll %d events happened \n", numEvents);
        fillActivateChannels(numEvents, activateChannels);
        // 进行扩容操作
        if(numEvents == events_.size()){
            events_.resize(2*numEvents);
        }
    }
    else if(numEvents == 0){
        LOG_INFO("EPollPoller::poll %s timeout! \n", __FUNCTION__);
    }

    return now;
}
/**
 * @brief 
 * 
 * @param channel 
 */
void EPollPoller::updateChannel(Channel* channel) {
    const int index = channel->index();
    LOG_INFO("fd=%d events=%d index=%d \n", channel->fd(), channel->events(), index);
    
    epoll_event  event;
    event.events = channel->events();
    event.data.fd = channel->fd();

    if(index == kNew || index == kDeleted)
    {
        // 如何channel 的状态是刚创建 未加入状态
        // 那么就将其加入ChannelMap 里面， 并且加入到epoll里面的红黑树
        if(index == kNew){
            int fd = channel->fd(); 
            channels_[fd] = channel;
        }
        channel->set_index(kAdded);
        update(EPOLL_CTL_ADD, channel);
    }else{
        int fd = channel->fd();
        if(channel->isNoneEvent()){
            update(EPOLL_CTL_DEL, channel);
            channel->set_index(kDeleted);
        }else{
            update(EPOLL_CTL_MOD, channel);
        }
        
    }
    //epoll_ctl(epollfd_, EPOLL_CTL_MOD, channel->fd(), &event);
}

void EPollPoller::update(int op, Channel* channel){
    epoll_event  event;
    memset(&event, 0, sizeof(event));
    event.events = channel->events();
    // 给event绑定channel
    event.data.ptr = channel;
    int fd = channel->fd();

    if(epoll_ctl(epollfd_, op, fd, &event) < 0){
        if(op == EPOLL_CTL_DEL){
            LOG_ERROR("EPollPoller::update epoll_ctl delete error: %d \n", errno);
        }else{
            LOG_FATAL("EPollPoller::update epoll_ctl add/mod error: %d \n", errno);
        }
    }

}
void EPollPoller::removeChannel(Channel* channel) {
    int fd = channel->fd();
    LOG_INFO("func %s -> fd:%d", __FUNCTION__, fd);
    if(channel->index() == kAdded)
        update(EPOLL_CTL_DEL, channel);

    channel->set_index(kDeleted);
    channels_.erase(fd);
}



// 填写活跃的连接
void EPollPoller::fillActivateChannels(int numEvents, ChannelList* activateChannels) const {
    for(int i=0; i<numEvents; i++){
        int fd =events_[i].data.fd;
        // events_[i].data.ptr 的实际类型就是Channel*
        Channel * channel = (Channel*) events_[i].data.ptr;
        // 将这次触发的感兴趣事件设置给channel， 以便channel进行回调
        channel->set_revent(events_[i].events);
        activateChannels->push_back(channel);
    }
}

